from CvPythonExtensions import *

import GerikSpells
from GerikSpells import GerikSpellBase
from GSGroupPolicies import GSAll as GSGroup
from GSHandlerPolicies import GSTargetting as GSHandler

from GSTargetInfoPolicies import GSSinglePlotTarget
from GSGraphicsPolicies import GSPlot

from GSResultsPolicies import GSMission as GSResults

import GerikSpellsUtils

gc = CyGlobalContext()

class Patrol(GerikSpellBase, GSGroup, GSHandler, GSResults):
    def __init__(self):
        GerikSpellBase.__init__(self)
        GSGroup.__init__(self)
        GSHandler.__init__(self)
        GSResults.__init__(self, GSSinglePlotTarget(self.canTargetPlot2))

    def canUnitCast(self, pCastingUnit, pPlot, bVisible):
        if (pCastingUnit.getUnitType() == gc.getInfoTypeForString("UNIT_WARRIOR")):
            return True

    def createTargettingStageList(self, bAlt, bShift, bCtrl):
        # This spell uses two stages, both being simple plot targetting.
        stageList = []

        pPlotTargetPolicy = GSSinglePlotTarget(self.canTargetPlot1)
        pPlotGraphicsPolicy = GSPlot()
        pPlotGraphicsPolicy.setCursorType("CURSOR_PATROL")
        stageList.append( (pPlotTargetPolicy, pPlotGraphicsPolicy) )

        pPlotTargetPolicy = GSSinglePlotTarget(self.canTargetPlot2)
        pPlotGraphicsPolicy = GSPlot()
        pPlotGraphicsPolicy.setCursorType("CURSOR_PATROL_BACK")
        stageList.append( (pPlotTargetPolicy, pPlotGraphicsPolicy) )

        return stageList



    def canTargetPlot1(self, pCastingGroup, pCastingPlot, pPotentialTarget, bVisible):
        # Don't allow plots we can't travel to
        if (CyMap().calculatePathDistance(pCastingGroup.plot(), pPotentialTarget) == -1):
            return False

        return True

    def canTargetPlot2(self, pCastingGroup, pCastingPlot, pPotentialTarget, bVisible):
        pPlot1 = self.getTargettingResults(0).getTarget()
        pPlot2 = pPotentialTarget

        # Don't allow for two of the same plots, because we'll start an inf. loop
        if (pPlot1.getX() == pPlot2.getX() and pPlot1.getY() == pPlot2.getY()):
            return False

        # Don't allow plots we can't travel to.
        if (CyMap().calculatePathDistance(pPlot1, pPlot2) == -1):
            return False

        return True

    def castSpell(self, pTargetInfo):
        # First, push the mission to move the unit to the first point.
        pPlot1 = self.getTargettingResults(0).getTarget()
        pPlot2 = pTargetInfo.getTarget()

        # First, push a move to mission to move the unit to the first plot.
        # This is a function not called on all computers, so we need to use the selectionListGameNetMessage function.
        gc.getGame().selectionListGameNetMessage(GameMessageTypes.GAMEMESSAGE_PUSH_MISSION, MissionTypes.MISSION_MOVE_TO,
                                                 pPlot1.getX(), pPlot1.getY(), -1, False, False)
        # Push the spell mission with these iData's.
        # iData1: plot1 X
        # iData2: plot1 Y
        # iData3: Combined plot2.X and plot2.Y, using the GerikSpellsUtils.combine function
        # Finally, be sure that the shift (append) is true so that we don't accidentally clear the mission queue with
        # the spell still in it
        self.pushSpellMissionAltShift(pPlot1.getX(), pPlot1.getY(), GerikSpellsUtils.combine(pPlot2.getX(), pPlot2.getY()),
                                        False, True)

    def startSpellMission(self, pCastingGroup, iData1, iData2, iData3):
        pPlot1 = CyMap().plot(iData1, iData2)
        pPlotX, pPlotY = GerikSpellsUtils.uncombine(iData3)
        pPlot2 = CyMap().plot(pPlotX, pPlotY)

        # First, check which plot we're at.
        # If we're at the second plot, move to the first.
        if (pCastingGroup.at(pPlot2.getX(), pPlot2.getY())):
            if (pCastingGroup.canMoveInto(pPlot1, False)):
                # Push the mission to go to the first, then this patrol mission again.
                pCastingGroup.pushMission(MissionTypes.MISSION_MOVE_TO, pPlot1.getX(), pPlot1.getY(), 0, True, False,
                                         MissionAITypes.NO_MISSIONAI, pPlot1, pCastingGroup.getHeadUnit())

                pCastingGroup.pushSpellMission(self.getSpellNumber(), iData1, iData2, iData3, True)
        # If we're at the first plot, move to the second.
        elif (pCastingGroup.at(pPlot1.getX(), pPlot1.getY())):
            if (pCastingGroup.canMoveInto(pPlot2, False)):
                pCastingGroup.pushMission(MissionTypes.MISSION_MOVE_TO, pPlot2.getX(), pPlot2.getY(), 0, True, False,
                                         MissionAITypes.NO_MISSIONAI, pPlot2, pCastingGroup.getHeadUnit())

                pCastingGroup.pushSpellMission(self.getSpellNumber(), iData1, iData2, iData3, True)

